package com.bj58.http.test;

import com.google.common.base.Joiner;
import com.peng.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.net.URIBuilder;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * BaseHttpCaller
 *
 * @author: lupeng10
 * @create: 2023-05-23 18:13
 */
@Slf4j
public abstract class BaseHttpCaller {

    protected static final CloseableHttpClient HTTP_CLIENT;

    static {
        RequestConfig requestConfig = RequestConfig.custom()
                // 从连接池获取可用连接的超时时间，单位毫秒
                .setConnectionRequestTimeout(10000, TimeUnit.MILLISECONDS)
                // 链接超时时间
                .setConnectTimeout(5000, TimeUnit.MILLISECONDS)
                // 响应超时时间
                .setResponseTimeout(5000, TimeUnit.MILLISECONDS)
                .build();

        HTTP_CLIENT = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

    protected abstract Map<String, Object> getHttpHeaders();

    public String get(String url, Map<String, String> params) {
        try {
            URIBuilder uriBuilder = new URIBuilder(url);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                uriBuilder.addParameter(entry.getKey(), entry.getValue());
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            for (Map.Entry<String, Object> entry : getHttpHeaders().entrySet()) {
                httpGet.addHeader(entry.getKey(), entry.getValue());
            }
            CloseableHttpResponse response = HTTP_CLIENT.execute(httpGet);
            print(response);
            int code = response.getCode();
            if (code >= 200 && code < 300) {
                String json = EntityUtils.toString(response.getEntity());
                log.info("【请求response】\n{}", JacksonUtil.toPrettyJson(JacksonUtil.ofJsonMap(json, HashMap.class, String.class, Object.class)));
                return json;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private void print(CloseableHttpResponse response) {
        log.info("【请求response-Phrase】{}", response.getReasonPhrase());
        String headersInfo = Joiner.on("\n").join(Arrays.stream(response.getHeaders()).map(h -> h.getName() + " : " + h.getValue()).collect(Collectors.toList()));
        log.info("【请求response-Header】\n{}", headersInfo);
    }

    public String post(String url, Map<String, String> params) {
        try {
            HttpPost post = new HttpPost(new URIBuilder(url).build());
            post.setHeader("Content-Type", ContentType.APPLICATION_JSON.toString());
            for (Map.Entry<String, Object> entry : getHttpHeaders().entrySet()) {
                post.addHeader(entry.getKey(), entry.getValue());
            }
            post.setEntity(new StringEntity(JacksonUtil.toJson(params), ContentType.APPLICATION_JSON));
            CloseableHttpResponse response = HTTP_CLIENT.execute(post);
            print(response);
            int code = response.getCode();
            if (code >= 200 && code < 300) {
                String json = EntityUtils.toString(response.getEntity());
                log.info("【请求response】\n{}", JacksonUtil.toPrettyJson(JacksonUtil.ofJsonMap(json, HashMap.class, String.class, Object.class)));
                return json;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
}
